package com.csot.ry.service.impl;

import java.io.File;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.atomic.LongAdder;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.stream.CollectorUtil;
import cn.hutool.core.stream.StreamUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.csot.common.core.domain.entity.SysDictData;
import com.csot.common.exception.ServiceException;
import com.csot.common.utils.DateUtils;
import com.csot.common.utils.DictUtils;
import com.csot.model.CitySegment;
import com.csot.model.RecordSegment;
import com.csot.ry.domain.RecordIpPojo;
import com.csot.ry.util.CacheKitUtil;
import com.csot.ry.util.UserUtils;
import com.jfinal.plugin.activerecord.Db;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.csot.ry.mapper.TRecordSegmentMapper;
import com.csot.ry.domain.TRecordSegment;
import com.csot.ry.service.ITRecordSegmentService;

/**
 * 备案表Service业务层处理
 *
 * @author csot
 * @date 2023-04-06
 */
@Service
public class TRecordSegmentServiceImpl implements ITRecordSegmentService {
    @Autowired
    private TRecordSegmentMapper tRecordSegmentMapper;

    private final CitySegment cityDao = new CitySegment().dao();

    private final RecordSegment recordDao = new RecordSegment().dao();

    /**
     * 查询备案表
     *
     * @param id 备案表主键
     * @return 备案表
     */
    @Override
    public TRecordSegment selectTRecordSegmentById(Long id) {
        return tRecordSegmentMapper.selectTRecordSegmentById(id);
    }

    /**
     * 查询备案表列表
     *
     * @param tRecordSegment 备案表
     * @return 备案表
     */
    @Override
    public List<TRecordSegment> selectTRecordSegmentList(TRecordSegment tRecordSegment) {
        return tRecordSegmentMapper.selectTRecordSegmentList(tRecordSegment);
    }

    /**
     * 新增备案表
     *
     * @param tRecordSegment 备案表
     * @return 结果
     */
    @Override
    public int insertTRecordSegment(TRecordSegment tRecordSegment) {
        String city = UserUtils.getCity();
        tRecordSegment.setIpCity(city);
        tRecordSegment.setCreateTime(DateUtils.getNowDate());
        tRecordSegment.setIpEndI(NetUtil.ipv4ToLong(tRecordSegment.getIpEnd()));
        tRecordSegment.setIpStartI(NetUtil.ipv4ToLong(tRecordSegment.getIpStart()));

        if (StrUtil.isBlank(city)) {
            throw new ServiceException(String.format("数据异常,异常原因：%s", "地市为空或格式不正确"));
        }
        try {
            tRecordSegment.setIpStartI(NetUtil.ipv4ToLong(tRecordSegment.getIpStart()));
            tRecordSegment.setIpEndI(NetUtil.ipv4ToLong(tRecordSegment.getIpEnd()));
        } catch (Exception e) {
            throw new ServiceException(String.format("数据异常,异常原因：%s", "IP地址为空或格式不正确"));
        }

        int record_count = Db.queryInt("select count(*) from t_record_segment where (ip_start_i <= ? and ip_end_i >= ?) or (ip_start_i <= ? and ip_end_i >= ?)",
                tRecordSegment.getIpStartI(), tRecordSegment.getIpStartI(), tRecordSegment.getIpEndI(), tRecordSegment.getIpEndI());
        if (record_count > 0) {
            throw new ServiceException(String.format("数据异常,异常原因：%s", "该行数据已经被导入"));
        }

        return tRecordSegmentMapper.insertTRecordSegment(tRecordSegment);
    }

    /**
     * 修改备案表
     *
     * @param tRecordSegment 备案表
     * @return 结果
     */
    @Override
    public int updateTRecordSegment(TRecordSegment tRecordSegment) {
        tRecordSegment.setUpdateTime(DateUtils.getNowDate());
        return tRecordSegmentMapper.updateTRecordSegment(tRecordSegment);
    }

    /**
     * 批量删除备案表
     *
     * @param ids 需要删除的备案表主键
     * @return 结果
     */
    @Override
    public int deleteTRecordSegmentByIds(Long[] ids) {
        return tRecordSegmentMapper.deleteTRecordSegmentByIds(ids);
    }

    /**
     * 删除备案表信息
     *
     * @param id 备案表主键
     * @return 结果
     */
    @Override
    public int deleteTRecordSegmentById(Long id) {
        return tRecordSegmentMapper.deleteTRecordSegmentById(id);
    }

    @Override
    public int importTRecordSegmentList(List<TRecordSegment> tRecordSegmentList) {
        List<RecordSegment> recordSegments = new ArrayList<>();
        for (int i = 0; i < tRecordSegmentList.size(); i++) {
            TRecordSegment tRecordSegment = tRecordSegmentList.get(i);
//            String city = DictUtils.getDictValue("ip_city", tRecordSegment.getIpCity().replace("市", ""));
//            if (StrUtil.isBlank(city)) {
//                throw new ServiceException(String.format("第%d行数据异常,异常原因：%s", i + 3, "地市为空或格式不正确"));
//            }
            try {
                tRecordSegment.setIpStartI(NetUtil.ipv4ToLong(tRecordSegment.getIpStart()));
                tRecordSegment.setIpEndI(NetUtil.ipv4ToLong(tRecordSegment.getIpEnd()));
            } catch (Exception e) {
                throw new ServiceException(String.format("第%d行数据异常,异常原因：%s", i + 3, "IP地址为空或格式不正确"));
            }

            int record_count = Db.queryInt("select count(1) from t_record_segment where (ip_start_i <= ? and ip_end_i >= ?) or (ip_start_i <= ? and ip_end_i >= ?)",
                    tRecordSegment.getIpStartI(), tRecordSegment.getIpStartI(), tRecordSegment.getIpEndI(), tRecordSegment.getIpEndI());
            if (record_count > 0) {
                throw new ServiceException(String.format("第%d行数据异常,异常原因：%s", i + 3, "该行数据已经被导入"));
            }
            int city_count = Db.queryInt("select count(1) from t_city_segment where (ip_start_i <= ? and ip_end_i >= ?) or (ip_start_i <= ? and ip_end_i >= ?)",
                    tRecordSegment.getIpStartI(), tRecordSegment.getIpStartI(), tRecordSegment.getIpEndI(), tRecordSegment.getIpEndI());
            if (city_count == 0) {
                throw new ServiceException(String.format("第%d行数据异常,异常原因：%s", i + 3, "该行数据在细粒度中不存在"));
            }

            RecordSegment rs = new RecordSegment();
            BeanUtils.copyProperties(tRecordSegment, rs);
            rs.setCreateTime(DateUtils.getNowDate());
//            rs.setIpCity(city);
            recordSegments.add(rs);
        }
        // 重复
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < recordSegments.size(); i++) {
            RecordSegment rs = recordSegments.get(i);
            for (int j = i + 1; j < recordSegments.size(); j++) {
                RecordSegment recordSegment = recordSegments.get(j);
                if (rs.getIpStartI() >= recordSegment.getIpStartI() && rs.getIpStartI() <= recordSegment.getIpEndI()) {
                    stringBuilder.append(String.format("第%d行数据异常,异常原因：%s", i + 3, "与第" + (j + 3) + "行重复"));
                    stringBuilder.append(System.lineSeparator());
                }

                if (rs.getIpEndI() >= recordSegment.getIpStartI() && rs.getIpEndI() <= recordSegment.getIpEndI()) {
                    stringBuilder.append(String.format("第%d行数据异常,异常原因：%s", i + 3, "与第" + (j + 3) + "行重复"));
                    stringBuilder.append(System.lineSeparator());
                }
            }
        }
        if (StrUtil.isNotBlank(stringBuilder.toString())) {
            File file = new File(System.getProperty("user.dir")
                    + "/text-chongfu-"
                    + System.currentTimeMillis() + ".txt");
            FileUtil.writeString(stringBuilder.toString(), file, Charset.defaultCharset());
            throw new ServiceException(stringBuilder.toString());
        }

        return Db.tx(() -> {

            Db.batchSave(recordSegments, 999);

            return true;
        }) ? recordSegments.size() : 0;


    }

    public List<RecordIpPojo> getDuiBiType(String type) {
        System.out.println("开始比对：" + type);
        List<CitySegment> citySegmentList = cityDao.findByCache("iplist", "city",
                "select ip_start,ip_start_i,ip_end,ip_end_i,ip_use_type,ip_city,ip_username from t_city_segment order by ip_start_i");
        List<RecordSegment> recordSegmentList = recordDao.findByCache("iplist", "record",
                "select ip_start,ip_start_i,ip_end,ip_end_i,IFNULL(record_city,'空') as record_city,allocate_type,company from t_record_segment");


        List<CitySegment> citySegmentListC = new ArrayList<>();
        CitySegment citySegmentTemp = null;
        for (CitySegment citySegment : citySegmentList) {
            if (citySegmentTemp == null) {
                citySegmentTemp = new CitySegment();
                BeanUtils.copyProperties(citySegment, citySegmentTemp);
                continue;
            }
            if ("use".equalsIgnoreCase(type)) {
                if (StrUtil.isNotBlank(citySegment.getIpUseType())
                        && citySegment.getIpCity().equalsIgnoreCase(citySegmentTemp.getIpCity())
                        && citySegment.getIpUseType().equalsIgnoreCase(citySegmentTemp.getIpUseType())
                        && citySegment.getIpStartI() == citySegmentTemp.getIpEndI() + 1) {
                    citySegmentTemp.setIpEndI(citySegmentTemp.getIpEndI() + 1);
                } else {
                    citySegmentTemp.setIpEnd(Ipv4Util.longToIpv4(citySegmentTemp.getIpEndI()));
                    citySegmentListC.add(citySegmentTemp);
                    citySegmentTemp = new CitySegment();
                    BeanUtils.copyProperties(citySegment, citySegmentTemp);
                }
            } else {
                if (StrUtil.isNotBlank(citySegment.getIpUsername()) &&
                        citySegment.getIpCity().equalsIgnoreCase(citySegmentTemp.getIpCity())
                        && citySegment.getIpUsername().equalsIgnoreCase(citySegmentTemp.getIpUsername())
                        && citySegment.getIpStartI() == citySegmentTemp.getIpEndI() + 1) {
                    citySegmentTemp.setIpEndI(citySegmentTemp.getIpEndI() + 1);
                } else {
                    citySegmentTemp.setIpEnd(Ipv4Util.longToIpv4(citySegmentTemp.getIpEndI()));
                    citySegmentListC.add(citySegmentTemp);
                    citySegmentTemp = new CitySegment();
                    BeanUtils.copyProperties(citySegment, citySegmentTemp);
                }
            }
        }
        citySegmentListC.add(citySegmentTemp);

        List<RecordIpPojo> recordIpPojos = new ArrayList<>(10000);
        List<SysDictData> sysDictDataList = DictUtils.getDictCache("ip_use_type");
        sysDictDataList.addAll(DictUtils.getDictCache("ip_city"));
        Map<String, String> dictMap = new HashMap<>();
        for (SysDictData sysDictData : sysDictDataList) {
            dictMap.put(sysDictData.getDictValue(), sysDictData.getDictLabel());
        }
        Map<String, List<CitySegment>> cityIpMap = CollStreamUtil.groupByKey(citySegmentListC, CitySegment::getIpCity);
        Map<String, List<RecordSegment>> recordMap = CollStreamUtil.groupByKey(recordSegmentList, RecordSegment::getRecordCity);
        Map<String, List<CitySegment>> cityMap = new HashMap<>();
        cityIpMap.forEach((k, v) -> {
            if (dictMap.containsKey(k))
                cityMap.put(dictMap.get(k), v);
        });
        System.out.println("-----------------");

        System.out.println(JSON.toJSONString(dictMap));

        System.out.println("-----------------");

        if ("use".equalsIgnoreCase(type)) {
            for (Map.Entry<String, List<RecordSegment>> entry : recordMap.entrySet()) {
                System.out.println("循环开始：" + entry.getKey() + "----" + entry.getValue().size());
                List<CitySegment> citySegments = cityMap.get(entry.getKey());
                if (Objects.isNull(citySegments)) {
                    citySegments = citySegmentListC;
                }
                System.out.println("细粒度数据：" + citySegments.size());
                for (RecordSegment recordSegment : entry.getValue()) {
                    for (CitySegment citySegment : citySegments) {
                        if ((citySegment.getIpStartI() <= recordSegment.getIpStartI() &&
                                citySegment.getIpEndI() >= recordSegment.getIpStartI())
                                || (citySegment.getIpStartI() <= recordSegment.getIpEndI() &&
                                citySegment.getIpEndI() >= recordSegment.getIpEndI())) {
                            System.out.println("导出数据：" + citySegment.getIpStart());
                            String usertype = dictMap.get(citySegment.getIpUseType());
                            if (StrUtil.isBlank(usertype)) {
                                usertype = citySegment.getIpUseType();
                            }
                            System.out.println("用途数据：" + usertype);
                            if ("未使用".equalsIgnoreCase(usertype)) {
                                if (!"预留".equalsIgnoreCase(recordSegment.getAllocateType())) {
                                    System.out.println("备案用途数据：" + recordSegment.getAllocateType());
                                    RecordIpPojo recordIpPojo = new RecordIpPojo();
                                    recordIpPojo.setIpEnd(citySegment.getIpEnd());
                                    recordIpPojo.setIpStart(citySegment.getIpStart());
                                    recordIpPojo.setRecordIpEnd(recordSegment.getIpEnd());
                                    recordIpPojo.setRecordIpStart(recordSegment.getIpStart());
                                    recordIpPojo.setIpUseType(usertype);
                                    recordIpPojo.setIpUsername(citySegment.getIpUsername());
                                    recordIpPojo.setCompany(recordSegment.getCompany());
                                    recordIpPojo.setAllocateType(recordSegment.getAllocateType());
                                    recordIpPojo.setRecordCity(recordSegment.getRecordCity());
                                    if (StrUtil.isBlank(recordIpPojo.getRecordCity()) || "空".equalsIgnoreCase(recordIpPojo.getRecordCity())) {
                                        if (dictMap.containsKey(citySegment.getIpCity()))
                                            recordIpPojo.setRecordCity(dictMap.get(citySegment.getIpCity()));
                                        else
                                            recordIpPojo.setRecordCity(citySegment.getIpCity());
                                    }
                                    recordIpPojos.add(recordIpPojo);
                                }
                                break;
                            }
                            if ("自用".equalsIgnoreCase(recordSegment.getAllocateType()) ||
                                    "分配且使用".equalsIgnoreCase(recordSegment.getAllocateType())) {

                            } else {
                                RecordIpPojo recordIpPojo = new RecordIpPojo();
                                recordIpPojo.setIpEnd(citySegment.getIpEnd());
                                recordIpPojo.setIpStart(citySegment.getIpStart());
                                recordIpPojo.setRecordIpEnd(recordSegment.getIpEnd());
                                recordIpPojo.setRecordIpStart(recordSegment.getIpStart());
                                recordIpPojo.setIpUseType(usertype);
                                recordIpPojo.setIpUsername(citySegment.getIpUsername());
                                recordIpPojo.setCompany(recordSegment.getCompany());
                                recordIpPojo.setAllocateType(recordSegment.getAllocateType());
                                recordIpPojo.setRecordCity(recordSegment.getRecordCity());
                                if (StrUtil.isBlank(recordIpPojo.getRecordCity()) || "空".equalsIgnoreCase(recordIpPojo.getRecordCity())) {
                                    if (dictMap.containsKey(citySegment.getIpCity()))
                                        recordIpPojo.setRecordCity(dictMap.get(citySegment.getIpCity()));
                                    else
                                        recordIpPojo.setRecordCity(citySegment.getIpCity());
                                }
                                recordIpPojos.add(recordIpPojo);
                            }
                            break;
                        }
                    }
                }
            }
        } else {
            for (Map.Entry<String, List<RecordSegment>> entry : recordMap.entrySet()) {
                List<CitySegment> citySegments = cityMap.get(entry.getKey());
                if (Objects.isNull(citySegments)) {
                    citySegments = citySegmentList;
                }
                if (Objects.isNull(citySegments)) {
                    continue;
                }
                for (RecordSegment recordSegment : entry.getValue()) {
                    for (CitySegment citySegment : citySegments) {
                        if ((citySegment.getIpStartI() <= recordSegment.getIpStartI() &&
                                citySegment.getIpEndI() >= recordSegment.getIpStartI())
                                || (citySegment.getIpStartI() <= recordSegment.getIpEndI() &&
                                citySegment.getIpEndI() >= recordSegment.getIpEndI())) {
                            String usertype = dictMap.get(citySegment.getIpUseType());
                            String ipusername = Optional.ofNullable(citySegment.getIpUsername()).orElse("");
                            String company = Optional.ofNullable(recordSegment.getCompany()).orElse("");
                            System.out.println("name:" + usertype + "--:" + ipusername + "----" + company);
                            if (!ipusername.equalsIgnoreCase(company)) {
                                RecordIpPojo recordIpPojo = new RecordIpPojo();
                                recordIpPojo.setIpEnd(citySegment.getIpEnd());
                                recordIpPojo.setIpStart(citySegment.getIpStart());
                                recordIpPojo.setRecordIpEnd(recordSegment.getIpEnd());
                                recordIpPojo.setRecordIpStart(recordSegment.getIpStart());
                                recordIpPojo.setCompany(recordSegment.getCompany());
                                recordIpPojo.setIpUseType(usertype);
                                recordIpPojo.setIpUsername(citySegment.getIpUsername());
                                recordIpPojo.setCompany(recordSegment.getCompany());
                                recordIpPojo.setAllocateType(recordSegment.getAllocateType());
                                recordIpPojo.setRecordCity(recordSegment.getRecordCity());
                                if (StrUtil.isBlank(recordIpPojo.getRecordCity()) || "空".equalsIgnoreCase(recordIpPojo.getRecordCity())) {
                                    if (dictMap.containsKey(citySegment.getIpCity()))
                                        recordIpPojo.setRecordCity(dictMap.get(citySegment.getIpCity()));
                                    else
                                        recordIpPojo.setRecordCity(citySegment.getIpCity());
                                }
                                recordIpPojos.add(recordIpPojo);
                            }
                            break;
                        }
                    }
                }
            }
        }

        System.out.println("结束比对：" + type);
        return recordIpPojos;
    }


}
